package com.lz.autotest.project.testmanage.reportmanage.service.impl;

import cn.hutool.core.thread.ThreadFactoryBuilder;
import com.lz.autotest.common.constant.ReportStatusConstants;
import com.lz.autotest.common.constant.ReportTypeConstants;
import com.lz.autotest.common.entity.ResponseVo;
import com.lz.autotest.common.exception.ServiceException;
import com.lz.autotest.common.utils.DateUtils;
import com.lz.autotest.common.utils.GlobalMap;
import com.lz.autotest.project.testmanage.infmanage.domain.InfResult;
import com.lz.autotest.project.testmanage.infmanage.domain.SstInf;
import com.lz.autotest.project.testmanage.reportmanage.domain.SstInfReport;
import com.lz.autotest.project.testmanage.reportmanage.domain.SstReportItem;
import com.lz.autotest.project.testmanage.reportmanage.mapper.InfReportMapper;
import com.lz.autotest.project.testmanage.reportmanage.service.InfReportService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;

import static java.math.BigDecimal.ROUND_HALF_UP;

/**
 * 接口管理 服务实现
 *
 * @author lz
 */
@Service
public class InfReportServiceImpl implements InfReportService {
    private static final Logger logger = LoggerFactory.getLogger(InfReportServiceImpl.class);
    @Resource
    private InfReportMapper infReportMapper;

    private static ExecutorService fixedPool = new ThreadPoolExecutor(1,
            2,
            1,
            TimeUnit.MILLISECONDS,
            new LinkedBlockingQueue<Runnable>(1000000),
            new ThreadFactoryBuilder().setNamePrefix("sstReport-save-pool-").build());

    @Override
    public List<SstInfReport> queryInfReportList(SstInfReport sstInfReport) {
        List<SstInfReport> list = infReportMapper.queryInfReportList(sstInfReport);
        return list;
    }

    @Override
    public int saveInfReport(SstInfReport sstInfReport) {
        return infReportMapper.saveInfReport(sstInfReport);
    }

    @Override
    public int saveInfReport(SstInf sstInf) {
        return infReportMapper.saveReport(sstInf);
    }

    @Override
    public void saveInfReportAsy(ResponseVo responseVo, SstInf sstInf) {

        fixedPool.execute(() -> {
            SstInfReport sstInfReport = new SstInfReport();
            InfResult infResponse = (InfResult) responseVo.getResult();
            sstInfReport.setReportId(sstInf.getSnowflakeId());
            sstInfReport.setReportName(infResponse.getInfName() + "_" + DateUtils.getCurr_YYYY_MM_DD_HH_MM_SS());
            sstInfReport.setReportType(ReportTypeConstants.SINGLE);
            sstInfReport.setCalcDate(DateUtils.getCurr_YYYY_MM_DD());
            sstInfReport.setInfId(infResponse.getInfId());
            sstInfReport.setStatus(ReportStatusConstants.DONE);
            sstInfReport.setResponseTime(sstInf.getResponseTime());
            sstInfReport.setRequestTime(sstInf.getRequestTime());
            sstInfReport.setConsumeTime(infResponse.getConsumeTime());
            sstInfReport.setMaxConsumeTime(infResponse.getMaxConsumeTime());
            sstInfReport.setAvgConsumeTime(infResponse.getAvgConsumeTime());
            sstInfReport.setMinConsumeTime(infResponse.getMinConsumeTime());
            sstInfReport.setCount(infResponse.getCount());
            sstInfReport.setSuccessCount(infResponse.getSuccessCount());
            sstInfReport.setFailCount(infResponse.getFailCount());
            sstInfReport.setRound(infResponse.getRound());
            sstInfReport.setConcurrency(infResponse.getConcurrency());
            sstInfReport.setSuccess(responseVo.isSuccess());
            sstInfReport.setInfEnv(infResponse.getInfEnv());
            sstInfReport.setInfName(infResponse.getInfName());
            sstInfReport.setInfMethod(infResponse.getInfMethod());
            sstInfReport.setInfUrl(infResponse.getInfUrl());
            infReportMapper.saveInfReport(sstInfReport);
        });
    }

    @Override
    public List queryAutoReportList(Map<String, Object> param) {
        List<SstInfReport> list = infReportMapper.queryAutoReportList(param);
        for (SstInfReport sstInfReport : list) {
            Map<String, Object> timeRange = new HashMap<>();
            timeRange.put("begTime", sstInfReport.getRequestTime());
            timeRange.put("endTime", sstInfReport.getResponseTime());
            sstInfReport.setPercentage((sstInfReport.getSuccessCount() / sstInfReport.getCount()) * 100);
        }
        return list;
    }

    @Override
    public List queryAutoReportListByExport(Map<String, Object> param) {
        List<SstInfReport> result = new ArrayList<>();
        List<SstInfReport> list = infReportMapper.queryAutoReportList(param);
        //根据ID进行排序
        Map<String, SstInfReport> reportMap = list.stream().collect(Collectors.toMap(SstInfReport::getReportId, SstInfReport -> SstInfReport));
        List<SstReportItem> items = infReportMapper.queryAutoReportItemList(list);

        Map<String, List<SstReportItem>> listMap = items.stream().collect(Collectors.groupingBy(data -> data.getReportId()));
        //对于多个
        for (String id : listMap.keySet()) {
            SstInfReport item = reportMap.get(id);
            List<String> infTimes = new ArrayList<>();
            Double[] ThreadTimes = new Double[listMap.get(id).size()];
            List<SstReportItem> itemList = listMap.get(id);
            for (int i = 0; i < itemList.size(); i++) {
                infTimes.add(itemList.get(i).getAllConsumeTime());
                ThreadTimes[i] = itemList.get(i).getConsumeTime();
            }
            item.setAllInfInfo(itemList.get(0).getAllInfInfo());
            item.setAllInfTimes(infTimes);
            item.setThreadTimes(ThreadTimes);
            double percentage = (item.getSuccessCount() / item.getCount()) * 100;
            BigDecimal decimal = new BigDecimal(percentage);
            decimal = decimal.setScale(2, ROUND_HALF_UP);
            item.setPercentage(decimal.doubleValue());
            result.add(item);
        }
        return result;
    }

    @Override
    public void deleteReport(List<String> ids) {
        infReportMapper.deleteReport(ids);
        infReportMapper.deleteReportItem(ids);
    }

    @Override
    public int saveInfReportItem(SstReportItem sstReportItem) {
        return infReportMapper.saveInfReportItem(sstReportItem);
    }

    @Override
    public List<SstReportItem> queryReportItemByIds(List<String> ids) {
        return infReportMapper.queryReportItemByIds(ids);
    }

    @Override
    public List<Map> getVersion(Map<String, Object> param) {
        return infReportMapper.getVersion(param);
    }

    @Override
    public List<SstInfReport> getReportByVersion(Map<String, Object> param) {
        return infReportMapper.getReportByVersion(param);
    }

    @Override
    public int updateTsstReport(Map<String, Object> param) {
        return infReportMapper.updateTsstReport(param);
    }

    @Override
    public void updateAutoStatus(String ip, SstReportItem sstReportItem) {
        Map<String, Object> map = new HashMap<>();
        map.put("reportId", sstReportItem.getReportId());
        List<SstReportItem> sstInfReports = infReportMapper.queryAutoReportItem(map);
        if (sstInfReports.size() == sstReportItem.getConcurrency()) {
            map.put("status", "0");
            String responseTime = DateUtils.getCurr_YYYY_MM_DD_HH_MM_SS();
            map.put("responseTime", responseTime);
            SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
            Long seconds = 0L;
            try {
                Date date1 = sdf.parse(sstReportItem.getRequestTime());
                Date date2 = sdf.parse(responseTime);
                seconds = (date2.getTime() - date1.getTime());
                //发送结束消息
//                pusher.sendOneMsg(ip,JSON.toJSONString(resultView));
                GlobalMap.updateInfResult(sstReportItem.getReportId(), null, 1, seconds / 1000);
            } catch (ParseException e) {
                throw new ServiceException(e.getMessage());
            }
            infReportMapper.updateStatus(map);
        }
    }

}